using System.Collections.Generic;
using UnityEngine;
using Utils;

namespace Game {
	public enum TerminalCommand : byte {
		None = 0,
		Clear = 1,
		RemoveLine = 2,
		PrintLine = 3,
	}

	public struct TerminalCommandEvent {
		public TerminalCommand Command;
		public string Args;

		public TerminalCommandEvent(TerminalCommand command, string args) {
			Command = command;
			Args = args;
		}
	}

	public sealed class ComputerTextTerminal : ITextTerminal {
		public const int MAX_LINE_COUNT = 50;
		public const int MAX_LINE_LENGTH = 1024;

		List<string> _terminalLines = new List<string>(MAX_LINE_COUNT);

		public EventBus<TerminalCommandEvent> OnTerminalCommand = new EventBus<TerminalCommandEvent>();

		public List<string> Messages => _terminalLines;

		public int LineCount => _terminalLines.Count;
		public string GetLine(int index) {
			if ( index < 0 || index >= _terminalLines.Count) {
				return string.Empty;
			}
			index = Mathf.Clamp(index, 0, _terminalLines.Count - 1);
			return _terminalLines[index];
		}

		public void AddMessage(string message) {
			if ( message == null) {
				message= string.Empty;
			}
			if ( message.Length > MAX_LINE_LENGTH ) {
				message = message.Substring(0, MAX_LINE_LENGTH);
			}
			_terminalLines.Add(message);
			if ( _terminalLines.Count > MAX_LINE_COUNT ) {
				_terminalLines.RemoveAt(0);
			}
			OnTerminalCommand.Fire(new TerminalCommandEvent(TerminalCommand.PrintLine, message));
		}

		public void SendLastMessagesToClient(int messageCount) {
			if ( messageCount <= 0 ) {
				return;
			}
			messageCount = Mathf.Min(messageCount, _terminalLines.Count - 1);
			for (int i = _terminalLines.Count - messageCount; i < _terminalLines.Count; i++) {
				OnTerminalCommand.Fire(new TerminalCommandEvent(TerminalCommand.PrintLine, _terminalLines[i]));
			}
		}

		public void AddErrorMessage(string message) {
			if (string.IsNullOrEmpty(message) ) {
				return;
			}
			AddMessage($"<color=#E80000>{message}</color>");
		}

		public void Clear() {
			_terminalLines.Clear();
			OnTerminalCommand.Fire(new TerminalCommandEvent(TerminalCommand.Clear, null));
		}

		public void RemoveLine(int lineCount) {
			lineCount = Mathf.Clamp(lineCount, 0, _terminalLines.Count);
			_terminalLines.RemoveRange(0, lineCount);
			OnTerminalCommand.Fire(new TerminalCommandEvent(TerminalCommand.RemoveLine, lineCount.ToString()));
		}

		public void AddMessage(object message) {
			AddMessage(message.ToString());
		}
	}
}
